home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / lang / lisp / stk-3.002 / stk-3 / STk-3.1 / Src / dynload.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-21  |  7.1 KB  |  245 lines

  1. /*
  2.  *
  3.  * d y n l o a d . c            -- All the stuff dealing with 
  4.  *                       dynamic loading
  5.  *
  6.  * Copyright ⌐ 1993-1996 Erick Gallesio - I3S-CNRS/ESSI <eg@unice.fr>
  7.  * 
  8.  *
  9.  * Permission to use, copy, and/or distribute this software and its
  10.  * documentation for any purpose and without fee is hereby granted, provided
  11.  * that both the above copyright notice and this permission notice appear in
  12.  * all copies and derived works.  Fees for distribution or use of this
  13.  * software or derived works may only be charged with express written
  14.  * permission of the copyright holder.  
  15.  * This software is provided ``as is'' without express or implied warranty.
  16.  *
  17.  * This software is a derivative work of other copyrighted softwares; the
  18.  * copyright notices of these softwares are placed in the file COPYRIGHTS
  19.  *
  20.  *
  21.  *           Author: Erick Gallesio [eg@kaolin.unice.fr]
  22.  *    Creation date: 23-Jan-1994 19:09
  23.  * Last file update: 21-Jul-1996 21:24
  24.  */
  25.  
  26. /* Support for HPUX is due to Dipankar Gupta <dg@hplb.hpl.hp.com> */
  27. /* Support for NETBSD is from Franke Ruediger (Ruediger.Franke@rz.tu-ilmenau.de) */
  28. /* Support for FreeBsD is due to Amancio Hasty Jr (hasty@netcom.com) */
  29. /* Support for Linux is inspired from Patrick Nguyen (pnguyen@elde.epfl.ch) */
  30.  
  31.  
  32. #if defined(SUNOS4) || defined(SUNOS5) || defined(IRIX5) || defined(OSF1)
  33. #include <dlfcn.h>
  34. #endif
  35.  
  36. #if defined(LINUX_DLD)
  37. #include <dld.h>
  38. #endif
  39.  
  40. #if defined(NETBSD1)         
  41. #include <sys/types.h>
  42. #include <nlist.h>
  43. #include <link.h>
  44. #define dlerror() "dlerror"  /* dlerror() isn't implemented in NetBSD 1.0 */
  45. #endif
  46.  
  47. #ifdef HPUX
  48. #include <dl.h>
  49. #endif
  50.  
  51. #include "stk.h"
  52.  
  53. #ifdef USE_DYNLOAD
  54. static SCM list_of_files = NULL;
  55.  
  56. #if defined(SUNOS4) || defined(SUNOS5) || defined(NETBSD1) || defined(FREEBSD) || defined(IRIX5) || defined(OSF1) ||defined(LINUX_ELF)
  57.  
  58. static void load_and_call(char *path, char *fct_name)
  59. {
  60.   static void *self_handle= NULL;
  61.   void *handle;
  62.   void (*init_fct)();
  63.   SCM str;
  64.  
  65.   /* Test if fct_name is already defined in the core interpreter
  66.   /* Don't do a dlopen with NULL more than one time since it seems to break
  67.   /* Solaris 2.3. (Moises Lejter <mlm@cs.brown.edu>) */
  68.   if (self_handle == NULL) 
  69.     if ((self_handle = (void *) dlopen(NULL,1)) == NULL)
  70.       Err("Cannot open myself !!!", NIL);
  71.  
  72.   if ((init_fct = (void (*)()) dlsym(self_handle, fct_name)) != NULL)
  73.     Err("Module is already (statically) loaded", STk_makestring(path));
  74.  
  75.   /* Try to avoid multiple loading */
  76.   if (!list_of_files) {
  77.     STk_gc_protect(&list_of_files);
  78.     list_of_files = NIL;
  79.   }
  80.   str = STk_makestring(path);
  81.   if (STk_member(str, list_of_files) != Ntruth) {
  82.     Err("Module is already (dynamically) loaded", str);
  83.   }
  84.   
  85.   /* Load file */
  86.   if ((handle = (void *) dlopen(path, 1)) == NULL) {
  87.     char msg[MAX_PATH_LENGTH];
  88. #ifdef FREEBSD
  89.     sprintf(msg, "Cannot open object file");
  90. #else
  91.     sprintf(msg, "Cannot open object file (%s)", dlerror());
  92. #endif
  93.     Err(msg, str);
  94.   }
  95.   
  96.   if ((init_fct = (void (*)()) dlsym(handle, fct_name)) == NULL) {
  97.     char msg[MAX_PATH_LENGTH];
  98.     
  99.     sprintf(msg, "Cannot find function \"%s\" in object file", fct_name);
  100.     Err(msg, NIL);
  101.   }
  102.   /* Call the init code */
  103.   (*init_fct)();
  104.   
  105.   list_of_files = Cons(str, list_of_files);
  106. }
  107. #endif
  108.  
  109. #if defined(LINUX_DLD)
  110. /* 
  111.  * This code is for Linux, using the dld package. This code should not be used 
  112.  * anymore when ELF will be completely accepted under Linux. In the meanwhile...
  113.  *
  114.  * This code is inspired from a code sent by Patrick Nguyen pnguyen@elde.epfl.ch.
  115.  *
  116.  */
  117.  
  118. static void load_and_call(char *path, char *fct_name)
  119. {
  120.   void *handle;
  121.   void (*init_fct)();
  122.   SCM str;
  123.   static dld_already_initialized = FALSE;
  124.  
  125.   /* Try to avoid multiple loading */
  126.   if (!list_of_files) {
  127.     STk_gc_protect(&list_of_files);
  128.     list_of_files = NIL;
  129.   }
  130.   str = STk_makestring(path);
  131.   if (STk_member(str, list_of_files) != Ntruth) {
  132.     Err("Module is already (dynamically) loaded", str);
  133.   }
  134.  
  135.   /* Dld must be initialized at first call */
  136.   if(!dld_already_initialized) {
  137.     if (dld_init (dld_find_executable (STk_Argv0)))
  138.       dld_perror("dld: failed to init dld");
  139.     else 
  140.       dld_already_initialized = TRUE;
  141.   }
  142.   
  143.   /* Load file */
  144.   if (dld_link(path)) dld_perror("dld: cannot link");
  145.  
  146.   /* And get a pointer on function "fct_name" */
  147.   init_fct = (void (*) ()) dld_get_func(fct_name);
  148.   if (init_fct) {
  149.     /* When loading a function. It can induce some unresolved references 
  150.      * Most of the time, the unresolved references come from fucntions
  151.      * which are in the libc but which are not used by the core interpreter.
  152.      * For instance, if loaded module uses fork, which is not loaded in
  153.      * the interpreter, we will have an unresolve reference for _fork.
  154.      * To avoid this problem, we make again a link against standard libc
  155.      * Note: in general situation is more complicated than this, unresolved 
  156.      * symbols could be elsewhere than the libc....
  157.      * Those situation are not handled by current code, but I hope that ELF 
  158.      * will supplant this way of doing dynamic loading soon...
  159.      */
  160.     if (dld_function_executable_p (fct_name))
  161.       /* Call the init code */
  162.       (*init_fct) ();
  163.     else {
  164.       /* Function is notexecutable = we have unresolved references */
  165.       if (dld_link("/usr/lib/libc.a") && dld_link("/usr/lib/libc.sa")) 
  166.     dld_perror("dld: cannot link"); 
  167.  
  168.       if (dld_function_executable_p (fct_name)) {
  169.     init_fct = (void (*) ()) dld_get_func(fct_name);
  170.     (*init_fct) ();
  171.       }
  172.       else {
  173.     char **unresolved;
  174.     extern int dld_undefined_sym_count; 
  175.     int i;      
  176.     fprintf(STk_stderr, "dld: function %s not executable!\n", fct_name);
  177.     fprintf(STk_stderr, "Unresolved symbols are:\n");
  178.     
  179.     unresolved= dld_list_undefined_sym();
  180.     for (i = 0; i < dld_undefined_sym_count; i++)
  181.       fprintf(STk_stderr, "\t%s\n",unresolved[i]);
  182.     free(unresolved);
  183.     Err("dld: link aborted", NIL);
  184.       }
  185.     }
  186.   }
  187.   else {
  188.     char msg[MAX_PATH_LENGTH];
  189.     sprintf(msg, "Cannot find function \"%s\" in object file", fct_name);
  190.     Err(msg, NIL);
  191.   }
  192.  
  193.   list_of_files = Cons(str, list_of_files);
  194. }
  195. #endif /* LINUX_DLD */
  196.  
  197. #ifdef HPUX
  198. static void load_and_call(char *path, char *fct_name)
  199. {
  200.   shl_t handle;
  201.   void (*init_fct)();
  202.  
  203.   if ((handle = shl_load(path, BIND_IMMEDIATE | BIND_VERBOSE, 0L)) == NULL) 
  204.     Err("Cannot open file", STk_makestring(path));
  205.   
  206.   handle = NULL;
  207.   if (shl_findsym(&handle, fct_name, TYPE_PROCEDURE, &init_fct) == -1) {
  208.     char msg[MAX_PATH_LENGTH];
  209.     
  210.     sprintf(msg, "Cannot find function %s in object file", fct_name);
  211.     Err(msg, NIL);
  212.   }
  213.   /* Call the init code */
  214.   (*init_fct)();
  215. }
  216. #endif
  217.  
  218. void STk_load_object_file(char *path)
  219. {
  220.   char fct_name[1024], *p, *slash, *dot;
  221.  
  222.   /* Load the file as an object one */
  223.  
  224.   for (p = path, slash = p-1; *p; p++)        /* Find position of last '/' */
  225.     if (*p == '/') slash = p;
  226.  
  227. #if defined(NETBSD1) || defined(FREEBSD)
  228.   sprintf(fct_name, "_STk_init_%s", slash + 1);
  229. #else
  230.   sprintf(fct_name, "STk_init_%s", slash + 1);
  231. #endif
  232.  
  233.   for (p = fct_name; *p; p++)            /* Delete suffix it it exists */
  234.       if (*p == '.') { *p = '\0'; break; }
  235.  
  236.   load_and_call(path, fct_name);
  237. }
  238.  
  239. #else /* not DYNLOAD */
  240. void STk_load_object_file(char *path)
  241. {
  242.   Err("load: Loading of object file is not defined on this architecture", NIL);
  243. }
  244. #endif
  245.